package org.example.springredis;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.List;
import java.util.Set;

@RestController
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @RequestMapping("/testString")
    public String testString() {
        redisTemplate.opsForValue().set("key1", "v1");
        redisTemplate.opsForValue().set("key2", "v2");
        redisTemplate.opsForValue().set("key3", "v3");
        return redisTemplate.opsForValue().get("key3");
    }

    @RequestMapping("/testList")
    public List<String> testList() {
        redisTemplate.execute((RedisConnection connection) -> {
            connection.flushAll();
            return null;
        });
        redisTemplate.opsForList().leftPush("list1", "333");
        redisTemplate.opsForList().leftPush("list1", "222");
        redisTemplate.opsForList().leftPush("list1", "111");
        redisTemplate.opsForList().rightPush("list1", "444");
        return redisTemplate.opsForList().range("list1", 0, -1);
    }

    @RequestMapping("/testSet")
    public Set<String> testSet() {
        redisTemplate.execute((RedisConnection connection) -> {
            connection.flushAll();
            return null;
        });
        redisTemplate.opsForSet().add("set1", "111", "222", "333");
        System.out.println(redisTemplate.opsForSet().size("set1"));
        return redisTemplate.opsForSet().members("set1");

    }


    public void placeOrder() throws InterruptedException {
        String productId = "acf435";
        Thread mainThread = Thread.currentThread();
        //使用分布式锁,
        while(redisTemplate.opsForValue().setIfAbsent(productId, Thread.currentThread().getName(), Duration.ofSeconds(10))) {
            //续命线程
            new Thread(() -> {
                //每隔5秒检测主线程是否在线，在线则延长key过期时间
                while (true) {
                    try {
                        Thread.sleep(5000);
                        if(mainThread.isAlive()) {
                            redisTemplate.opsForValue().setIfPresent(productId, mainThread.getName(), Duration.ofSeconds(10));
                        }else{
                            Thread.currentThread().interrupt();
                        }
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }

            }).start();
            try {

                Long stock = Long.parseLong(redisTemplate.opsForValue().get("stock"));
                if (stock > 0) {
                    Thread.sleep(100);
                    redisTemplate.opsForValue().set("stock", String.valueOf(--stock));
                    System.out.println(Thread.currentThread().getName() + "秒杀成功");
                } else {
                    System.out.println(Thread.currentThread().getName() + "秒杀失败，库存不足");
                }
                break;
            }finally {
                //释放锁
                redisTemplate.delete(productId);
            }
        };

    }

    @RequestMapping("/main")
    public void main(String[] args) {
        for(int i = 0; i < 3; i++) {
            new Thread(() -> {
                try {
                    placeOrder();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }
    }
}
